package com.sunrate.investingquote.service.router;

import com.sunrate.investingquote.bean.router.ChannelInfo;
import com.sunrate.investingquote.bean.router.ChannelPriorityConfig;
import com.sunrate.investingquote.bean.router.ChannelRouter;
import com.sunrate.investingquote.dao.router.ChannelInfoDao;
import com.sunrate.investingquote.dao.router.ChannelPriorityConfigDao;
import com.sunrate.investingquote.dao.router.ChannelRouterDao;
import com.sunrate.investingquote.dto.router.Order;
import com.sunrate.investingquote.dto.router.OrderRouterParam;
import com.sunrate.investingquote.dto.router.comparator.RouterSortContext;
import com.sunrate.investingquote.enums.RouterPriorityEnum;
import com.sunrate.investingquote.service.router.comparator.RouterComparatorContext;
import com.sunrate.investingquote.service.router.comparator.test.compare.v1.ChainParam;
import com.sunrate.investingquote.service.router.comparator.test.compare.v1.ComparatorChain;
import com.sunrate.investingquote.service.router.match.RouterMatchContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yyh
 * @description:
 * @date 2023/06/29/ 11:54
 */
@Service
@Slf4j
public class ChannelRouterServiceImpl implements ChannelRouterService {


    @Autowired
    private RouterMatchContext routerMatchContext;
    @Autowired
    private ChannelRouterDao routerDao;
    @Autowired
    private ChannelPriorityConfigDao priorityConfigDao;
    @Autowired
    private ChannelInfoDao channelInfoDao;

    @Override
    public List<ChannelRouter> getChannelRouters(Order order) {
        checkOrderInfo(order);
        List<ChannelRouter> routerList = routerDao.listByStatus(0);
        if (CollectionUtils.isEmpty(routerList)) {
            throw new RuntimeException("匹配支付渠道失败[无启用的支付渠道配置]");
        }
        List<ChannelRouter> routerResultList = new ArrayList<>();
        //匹配
        for (ChannelRouter router : routerList) {
            OrderRouterParam param = new OrderRouterParam();
            param.setBeneBankCode(order.getBeneBankCode());
            param.setBeneCtryCode(order.getBeneCtryCode());
            param.setDebitAmt(order.getDebitAmt());
            param.setDebitCur(order.getDebitCur());
            if (routerMatchContext.match(param, router)) {
                routerResultList.add(router);
            }
        }
        if (CollectionUtils.isEmpty(routerResultList)) {
            return routerResultList;
        }
        //优先级排序
        return sort(routerResultList);
    }


    private List<ChannelRouter> sort(List<ChannelRouter> channelRouterList) {
        List<ChannelPriorityConfig> configList = priorityConfigDao.listByStatus(0);
        if (CollectionUtils.isEmpty(configList)) {
            return channelRouterList;
        }
        List<RouterSortContext<ChannelRouter>> contextList = new ArrayList<>();
        Map<String, String> config = configList.stream().collect(Collectors.toMap(ChannelPriorityConfig::getCode, ChannelPriorityConfig::getCode));
        for (ChannelRouter channelRouter : channelRouterList) {
            RouterSortContext<ChannelRouter> context = new RouterSortContext<>();
            context.setDefaultPriority(channelRouter.getPriority());
            context.setData(channelRouter);
            ChannelInfo channelInfo = channelInfoDao.getByChannelCode(channelRouter.getChannelCode());
            if (config.containsKey(RouterPriorityEnum.FEE_RATE.getCode())) {
                context.setFeeRate(channelInfo.getFeeRate());
            }
            if (config.containsKey(RouterPriorityEnum.COST_TIME.getCode())) {
                context.setCostTime(channelInfo.getCostTime());
            }
            contextList.add(context);
        }
//        Comparator<RouterSortContext<ChannelRouter>> comparator = RouterComparatorContext.create(configList);
//        contextList.sort(comparator);

        ChainParam chainParam = new ChainParam();
        chainParam.setConfigs(configList);
        ComparatorChain chain = new ComparatorChain(chainParam);
        chain.createComparator();
        contextList.sort(chainParam.getComparator());
        return contextList.stream().map(RouterSortContext::getData).collect(Collectors.toList());
    }

    /**
     * @param order
     */
    private void checkOrderInfo(Order order) {
        if (StringUtils.isEmpty(order.getBeneBankCode())) {
            throw new RuntimeException("匹配支付渠道失败[收款银行swiftCode为空]");
        }
        if (StringUtils.isEmpty(order.getBeneCtryCode())) {
            throw new RuntimeException("匹配支付渠道失败[收款银行所属国家为空]");
        }
        if (StringUtils.isEmpty(order.getDebitCur())) {
            throw new RuntimeException("匹配支付渠道失败[付款币种为空]");
        }
        if (order.getDebitAmt() == null) {
            throw new RuntimeException("匹配支付渠道失败[付款金额为空]");
        }
    }

}
